package com.electronic.utils;


import com.cebpubservice.cashare.sdk.electronicsealsignatureandverifysignature.GetCAOrgCertChainInfo;
import com.cebpubservice.cashare.sdk.electronicsealsignatureandverifysignature.param.QueryCAOrgCertChainInfoParamDTO;
import com.cebpubservice.cashare.sdk.electronicsealsignatureandverifysignature.result.BatchGetCAOrgCertChainInfoResultDTO;
import com.electronic.enums.CertAlgEnum;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;
import org.springframework.stereotype.Component;
import org.springframework.util.Base64Utils;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.security.cert.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

/**
 * @Author: IFCA
 * @Description: 证书链工具类
 */
@Slf4j
@Component
public class CertChainsUtil {




    /**
     * base64证书链内容转为证书
     */
    public static Collection<X509Certificate> convertBase64StringToCertificates(String base64CertChain) {
        try {
            // 去除换行符
            base64CertChain= base64CertChain.replaceAll("\n", "");
            Collection<X509Certificate> certificates = new ArrayList<>();
            //证书链字节数组
            byte[] certChainBytes = Base64Utils.decodeFromString(base64CertChain);
            Security.addProvider(new BouncyCastleProvider());
            CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");
            ByteArrayInputStream in = new ByteArrayInputStream(certChainBytes);
            while (in.available() > 0) {
                X509Certificate cert = (X509Certificate) cf.generateCertificate(in);
                certificates.add(cert);
            }
            return certificates;
        } catch (Exception e) {
//            log.error("证书链Base64字符串转证书链对象异常", e);
            return null;
        }
    }




    /**
     * 证书链验证
     */
    public static X509Certificate findCACert(X509Certificate userCert, Collection<X509Certificate> certChain) {
        Iterator certIt = certChain.iterator();

        while (true) {
            X509Certificate cert;
            do {
                if (!certIt.hasNext()) {
                    return null;
                }

                cert = (X509Certificate) certIt.next();
            } while (!cert.getSubjectDN().equals(userCert.getIssuerDN()));

            try {
                userCert.verify(cert.getPublicKey());
                return cert;
            } catch (Exception var5) {
            }
        }
    }

    /**
     * 生成 X509CRL 对象，用于表示证书吊销列表（CRL）
     */
    public static X509CRL generateCRL(InputStream inStream) throws CRLException {
        if (!((InputStream) inStream).markSupported()) {
            inStream = new BufferedInputStream((InputStream) inStream);
        }

        try {
            ((InputStream) inStream).mark(10);
            if (((InputStream) inStream).read() != 48) {
                ((InputStream) inStream).reset();
                return readPEMCRL((InputStream) inStream);
            } else {
                ((InputStream) inStream).reset();
                return readDERCRL((InputStream) inStream);
            }
        } catch (Exception var2) {
            throw new CRLException(var2.toString());
        }
    }

    /**
     * 读取证书内容
     */
    private static X509CRL readDERCRL(InputStream inStream) throws IOException, CRLException, CertificateException, NoSuchProviderException {
        X509CRL cRL = (X509CRL) CertificateFactory.getInstance("X.509", "BC").generateCRL(inStream);
        inStream.close();
        return cRL;
    }

    /**
     * 读取证书内容
     */
    private static X509CRL readPEMCRL(InputStream inStream) throws IOException, CRLException, CertificateException, NoSuchProviderException {
        StringBuffer pemBuf = new StringBuffer();

        String line;
        while ((line = readLine(inStream)) != null) {
            if (!line.equals("-----BEGIN CRL-----") && !line.equals("-----BEGIN X509 CRL-----") && !line.equals("-----END CRL-----") && !line.equals("-----END X509 CRL-----")) {
                pemBuf.append(line);
            }
        }

        if (pemBuf.length() != 0) {
            ByteArrayInputStream bIn = new ByteArrayInputStream(Base64.decode(pemBuf.toString()));
            return readDERCRL(bIn);
        } else {
            return null;
        }
    }

    /**
     * 内容读取
     */
    private static String readLine(InputStream inStream) throws IOException {
        StringBuffer l = new StringBuffer();

        int c;
        while ((c = inStream.read()) != 10 && c >= 0) {
            if (c != 13) {
                l.append((char) c);
            }
        }

        return l.length() == 0 && c < 0 ? null : l.toString();
    }

    /**
     * 读取并转换JSON文件
     *
     * @param filePath
     * @return
     */
    public static List<BatchGetCAOrgCertChainInfoResultDTO> readAndConvert(String filePath) {

        if (filePath == null|| filePath.isEmpty()){
            return new ArrayList<>();
        }
        try {
            // 使用Files.readAllBytes方法读取文件的全部内容
            byte[] jsonData = Files.readAllBytes(Paths.get(filePath));
            String jsonString = new String(jsonData, StandardCharsets.UTF_8); // 指定字符编码为UTF-8

            // 使用Jackson ObjectMapper解析JSON字符串
            ObjectMapper objectMapper = new ObjectMapper();
            List<BatchGetCAOrgCertChainInfoResultDTO> resultList = objectMapper.readValue(jsonString,
                    objectMapper.getTypeFactory().constructCollectionType(List.class, BatchGetCAOrgCertChainInfoResultDTO.class));
            log.info("读取并转换JSON文件成功");
            return resultList;
        } catch (IOException e) {
            log.info("读取并转换JSON文件失败");
            // 处理文件读取过程中可能出现的IO异常
            return new ArrayList<>();
        }
    }

    /**
     * 根据证书获取证书链
     * @param certificate
     * @return
     */
    public static String certificateChain(Certificate certificate)  {
        try {
            X509Certificate x509Certificate = IFCAUtil.readX509Certificate(certificate.getEncoded());
            //获取证书颁发机构
            String issuerDN = x509Certificate.getIssuerDN().getName();
            //获取证书中签发者的O项
            String issuerO = ICertUtil.convertToKeyValues(issuerDN).get("O");
            //加密类型
            String sigAlgName = x509Certificate.getSigAlgName();
            String keyAlg = null;
            //加密类型数值
            if (CertAlgEnum.RSA.getPkcs10SignAlg().equalsIgnoreCase(sigAlgName)){
                keyAlg="01";
            }else {
                keyAlg="00";
            }
            //证书链O值集合
            List<String> caOrgCertChainCodes= new ArrayList<>();
            caOrgCertChainCodes.add(issuerO);
            //调用SDK参数
            QueryCAOrgCertChainInfoParamDTO queryCAOrgCertChainInfoParamDTO= new QueryCAOrgCertChainInfoParamDTO();
            queryCAOrgCertChainInfoParamDTO.setCaOrgCertChainCodes(caOrgCertChainCodes);
            //根据加密类型获取证书链
            List<BatchGetCAOrgCertChainInfoResultDTO> batchGetCAOrgCertChainInfoResultDTOS = GetCAOrgCertChainInfo.queryCAOrgCertChainInfo(queryCAOrgCertChainInfoParamDTO);
            //遍历证书链
            if (!batchGetCAOrgCertChainInfoResultDTOS.isEmpty()){
                for (BatchGetCAOrgCertChainInfoResultDTO batchGetCAOrgCertChainInfoResultDTO : batchGetCAOrgCertChainInfoResultDTOS){
                    //判断证书链加密类型是否匹配
                    if (keyAlg.equals(batchGetCAOrgCertChainInfoResultDTO.getPublicKeyAlgorithm())){
                        //返回证书链
                        return batchGetCAOrgCertChainInfoResultDTO.getCertificateChain();
                    }
                }
            }
        }catch (Exception e){
            log.info("根据证书获取证书链失败");
            return null;
        }

        return null;
    }
}
